package io.youngledo.usb.license;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;

/// 许可证管理器
///
/// 负责许可证的加载、保存和管理。
/// 这是应用程序与许可证系统交互的主要入口点。
///
/// ## 功能
/// - 从文件加载许可证
/// - 保存许可证到文件
/// - 验证许可证有效性
/// - 提供当前许可证信息
///
/// ## 许可证文件位置
/// - **默认路径**: `~/.universal-storage-browser/license.json`
/// - 文件格式：JSON
/// - 编码：UTF-8
@Slf4j
public class LicenseManager {

    private static final Path LICENSE_FILE_PATH = Path.of(
            System.getProperty("user.home"),
            ".universal-storage-browser",
            "license.json"
    );

    private static License currentLicense;
    private static final ObjectMapper objectMapper = createObjectMapper();

    /// 创建配置好的ObjectMapper
    ///
    /// @return 配置好的ObjectMapper实例
    private static ObjectMapper createObjectMapper() {
        var mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return mapper;
    }

    /// 初始化许可证管理器
    ///
    /// 在应用程序启动时调用，加载许可证文件。
    /// 如果许可证文件不存在或无效，将使用默认的社区版许可证。
    public static void initialize() {
        log.info("初始化许可证管理器...");

        // 尝试加载许可证文件
        var loadedLicense = loadLicenseFromFile();

        if (loadedLicense.isPresent()) {
            var license = loadedLicense.get();

            // 验证许可证
            if (LicenseValidator.validateLicense(license)) {
                currentLicense = license;
                log.info("✅ 许可证加载成功: {} ({})",
                        license.type().getDisplayName(),
                        license.userName());
            } else {
                log.warn("⚠️  许可证验证失败，使用社区版");
                useCommunityLicense();
            }
        } else {
            log.info("未找到许可证文件，使用社区版");
            useCommunityLicense();
        }
    }

    /// 使用社区版许可证
    private static void useCommunityLicense() {
        currentLicense = License.createCommunityLicense();
        log.info("当前使用: {}", currentLicense.type().getDisplayName());
    }

    /// 从文件加载许可证
    ///
    /// @return 如果加载成功返回License对象，否则返回空Optional
    private static Optional<License> loadLicenseFromFile() {
        try {
            if (!Files.exists(LICENSE_FILE_PATH)) {
                log.debug("许可证文件不存在: {}", LICENSE_FILE_PATH);
                return Optional.empty();
            }

            var json = Files.readString(LICENSE_FILE_PATH);
            var license = objectMapper.readValue(json, License.class);
            log.info("从文件加载许可证: {}", LICENSE_FILE_PATH);
            return Optional.of(license);

        } catch (Exception e) {
            log.error("加载许可证文件失败", e);
            return Optional.empty();
        }
    }

    /// 保存许可证到文件
    ///
    /// @param license 要保存的许可证对象
    /// @throws Exception 如果保存失败
    public static void saveLicenseToFile(License license) throws Exception {
        // 确保目录存在
        Files.createDirectories(LICENSE_FILE_PATH.getParent());

        // 序列化为JSON并保存
        var json = objectMapper.writeValueAsString(license);
        Files.writeString(LICENSE_FILE_PATH, json);

        log.info("✅ 许可证已保存到: {}", LICENSE_FILE_PATH);
    }

    /// 激活许可证
    ///
    /// 验证并激活新的许可证。
    /// 如果验证成功，将保存许可证文件并更新当前许可证。
    ///
    /// @param license 要激活的许可证
    /// @return 如果激活成功返回true
    public static boolean activateLicense(License license) {
        log.info("正在激活许可证: {}", license.licenseKey());

        // 验证许可证
        if (!LicenseValidator.validateLicense(license)) {
            log.error("❌ 许可证验证失败");
            return false;
        }

        try {
            // 保存到文件
            saveLicenseToFile(license);

            // 更新当前许可证
            currentLicense = license;

            log.info("✅ 许可证激活成功: {} ({})",
                    license.type().getDisplayName(),
                    license.userName());
            return true;

        } catch (Exception e) {
            log.error("许可证激活失败", e);
            return false;
        }
    }

    /// 获取当前许可证
    ///
    /// @return 当前生效的许可证对象
    public static License getCurrentLicense() {
        if (currentLicense == null) {
            initialize();
        }
        return currentLicense;
    }

    /// 获取当前许可证类型
    ///
    /// @return 当前许可证类型
    public static LicenseType getCurrentLicenseType() {
        return getCurrentLicense().type();
    }

    /// 判断当前是否为社区版
    ///
    /// @return 如果是社区版返回true
    public static boolean isCommunityEdition() {
        return getCurrentLicenseType() == LicenseType.COMMUNITY;
    }

    /// 判断当前是否为付费版本（专业版或企业版）
    ///
    /// @return 如果是付费版本返回true
    public static boolean isPaidEdition() {
        return getCurrentLicenseType().isPaid();
    }

    /// 获取许可证文件路径
    ///
    /// @return 许可证文件的完整路径
    public static Path getLicenseFilePath() {
        return LICENSE_FILE_PATH;
    }

    /// 重置许可证（恢复为社区版）
    ///
    /// 删除许可证文件并切换回社区版。
    /// 通常在许可证过期或用户主动降级时使用。
    public static void resetToCommunit() {
        try {
            if (Files.exists(LICENSE_FILE_PATH)) {
                Files.delete(LICENSE_FILE_PATH);
                log.info("许可证文件已删除");
            }

            useCommunityLicense();
            log.info("已重置为社区版");

        } catch (Exception e) {
            log.error("重置许可证失败", e);
        }
    }

    /// 检查许可证状态
    ///
    /// 重新验证当前许可证，如果无效则降级为社区版。
    /// 建议在应用程序启动时和定期（如每次打开）调用。
    public static void checkLicenseStatus() {
        if (currentLicense == null || currentLicense.type() == LicenseType.COMMUNITY) {
            return; // 社区版无需检查
        }

        if (!LicenseValidator.validateLicense(currentLicense)) {
            log.warn("⚠️  许可证验证失败，降级为社区版");
            useCommunityLicense();
        }
    }

    /// 获取许可证信息摘要
    ///
    /// @return 格式化的许可证信息字符串
    public static String getLicenseInfo() {
        return getCurrentLicense().getDisplayInfo();
    }
}
